package org.lex.ftp.ui.speed;

import java.util.Arrays;
import java.util.List;

import javax.swing.ProgressMonitor;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.lex.filter.Filter;
import org.lex.ftp.util.Monitorable;
import org.lex.ftp.util.StatusBar;
import org.lex.ftp.util.ThreadPool;
import org.lex.net.ftp.FTPURL;


public class TestManager implements Runnable, ChangeListener, Monitorable {
	private SpeedTableModel tableModel = null;
	private StatusBar statusPane = null;
	private Filter filter = null;
	private ProgressMonitor progressMonitor = null;
	private List<FTPURL> ftpUrls = null;
	private int completeCounter = 0;
	private long startTime = 0L;
	private int[] statistic = null;
	private ChangeListener changeListener = null;
	private boolean showProgressMonitor = true;

	public TestManager(StatusBar statusPane, SpeedTableModel model) {
		this.statusPane = statusPane;
		this.tableModel = model;
		this.statistic = new int[ServerStatus.values().length];
	}

	public void setFilter(Filter filter) {
		this.filter = filter;
	}

	public void setChangeListener(ChangeListener changeListener) {
		this.changeListener = changeListener;
	}

	public long elapsedTime() {
		return System.currentTimeMillis() - this.startTime;
	}

	public boolean isFinished() {
		return this.getValue() == this.getMaximum();
	}

	public long getMaximum() {
		if (null == this.ftpUrls)
			return 0L;
		return this.ftpUrls.size();
	}

	public long getValue() {
		return this.completeCounter;
	}

	public void startTest(boolean showProgressMonitor) {
		// get prepared
		this.completeCounter = 0;
		this.startTime = System.currentTimeMillis();
		this.ftpUrls = tableModel.ftpUrls;
		Arrays.fill(this.statistic, 0);
		if (true == showProgressMonitor) {
			progressMonitor = new ProgressMonitor(null, "���ڲ��Է�����...", "", 0, ftpUrls.size() - 1);
			progressMonitor.setProgress(0);
			progressMonitor.setMillisToDecideToPopup(0);
			progressMonitor.setMillisToPopup(0);
		}
		this.showProgressMonitor = showProgressMonitor;
		ThreadPool.execute(this);
	}

	public void run() {
		for (int i = 0; i < ftpUrls.size(); i++) {
			TestThread testThread = new TestThread(filter, ftpUrls.get(i), i);
			testThread.setChangeListener(this);
			ThreadPool.execute(testThread);
		}
	}

	public synchronized void stateChanged(ChangeEvent e) {
		completeCounter++;
		if (true == this.showProgressMonitor) {
			progressMonitor.setProgress(completeCounter);
			progressMonitor.setNote(completeCounter + " of " + ftpUrls.size() + " Complete");
		}
		TestThread testThread = (TestThread) e.getSource();
		tableModel.setStatus(testThread.id, testThread.status);
		if (ServerStatus.Found == testThread.status)
			tableModel.setSpeed(testThread.id, testThread.speed);
		tableModel.fireTableDataChanged();
		statusPane.setStatus(this.getStatistic(testThread));
		if (null != this.changeListener)
			this.changeListener.stateChanged(e);
		System.out.println("ID: " + testThread.id + "\tHost: " + testThread.url.getHost() + "\n#Total: " + ftpUrls.size() + "\t#Finished: "
				+ completeCounter);
	}

	private String getStatistic(TestThread testThread) {
		if ((ServerStatus.Found == testThread.status) && (0 != testThread.speed)) {
		} else
			this.statistic[testThread.status.ordinal()]++;
		StringBuilder buffer = new StringBuilder();
		buffer.append(statistic[0]).append(" Failed, ");
		buffer.append(statistic[1]).append(" Target not found, ");
		buffer.append(statistic[2]).append(" Good, ");
		buffer.append(statistic[3]).append(" not tested");
		return buffer.toString();
	}
}
